package com.lb.annotationmapper;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lb.utils.JsonUnderLineConvertUtils;
import com.lb.utils.MyBatisReflectUtil;
import com.lb.utils.PageBean;
import com.lb.utils.PageList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 注：本类所执行sql时的封装建议安全sql占位如#{pwd}，也可以非占位，但自己要处理好，详见如下解释
 * MybatisBaseDaoCRUD基接口
 *
 * @param <T> 处理的POJO对象
 *            公共方法使用注解实现，较简便
 *            * 为处理sql安全和严谨
 *            1、建议使用占位符#{key},如使用${key}或使用通用sql语句查询，请自行过滤非法字符
 *            2、建议使用<![CDATA[#{key}]]>,例：select * from sys_user  where email=<![CDATA[#{email}]]> and pwd=<![CDATA[#{pwd}]]>
 *            可以处理“‘”、“""”区分的问题
 *            3、模糊查询请使用自定义动态sql,进行判断和拼接可安全的sql，注意like 取值使用${key}
 *            4、排序字段desc,asc，模糊like,分页标识如 limit,top  均使用${key}
 *            5、此支持最强大的script动态构建sql脚本，如果使用熟练完全可取代xml mapping映射的方法
 */
//@Repository
@SuppressWarnings("all")
public class MybatisBaseDaoCRUD  {
    @Autowired
    private BaseMapperCRUD bmc;

    public BaseMapperCRUD getBaseMapperCRUD() {
        return bmc;
    }

/*
    */
/**
     * @param Any
     * @Description: 通用id实体删除
     *//*

    @Transactional
    public int deleteById(String id) {
        Class clazz = getEntityClass();
        return getBaseMapperCRUD().deleteById(clazz, id);
    }
*/

    /**
     * @param Any
     * @Description: 通用id实体删除
     */
    @Transactional
    public int deleteById(Class clz, String id) {
        return getBaseMapperCRUD().deleteById(clz, id);
    }

    /**
     * @param Any
     * @Description: 通用实体删除
     */
    @Transactional
    public int deleteObject(Object entity) {

        return getBaseMapperCRUD().delete(entity);
    }

    /**
     * @param Any
     * @Description: 适用数据表手动分布式ID通用实体保存
     */
    @Transactional
    public int saveObject(Object entity) {
        return getBaseMapperCRUD().insert(entity);
    }

    /**
     * @param Any
     * @Description: 适用数据表自增ID，通用实体保存
     */
    @Transactional
    public int saveObjectReturnId(Object entity) {
        return getBaseMapperCRUD().insertReturnId(entity);
    }

    /**
     * @param Any
     * @Description: 部分更新对象不为nul的字段，性能高；主键id不能为null;通用实体更新
     */
    @Transactional
    public int updateObject(Object entity) {
        return getBaseMapperCRUD().update(entity);
    }

    /**
     * @param Any
     * @Description: 全更新对象全字段，存在字段的数据更新，其余更新为null；性能慢；如若进行orm持久化更新，请赋值字段，自控制好记录版本；通用实体更新
     */
    @Transactional
    public int updateObjectNew(Object entity) {
        return getBaseMapperCRUD().updateNew(entity);
    }

    /**
     * @Description: 通用实体更新
     * @param  Any
     */
    @Transactional
    public int updateNewByWhereMap(Object entity,Map<String,Object> whereMap){
        return getBaseMapperCRUD().updateNewByWhereMap(entity,whereMap);
    }

    /**
     * @param Any
     * @Description: 通用实体更新
     */
    @Transactional
    public int updateNewByWhere(Object entity, Map<String, Object> whereMap) {
        return getBaseMapperCRUD().updateNewByWhere(entity, whereMap);
    }


    /**
     * @param Any
     * @Description: 通用实体更新
     */
    @Transactional
    public int updateNewByWhereSql(Object entity, String otherWhereSql) {
        return getBaseMapperCRUD().updateNewByWhereSql(entity, otherWhereSql);
    }

    /**
     * /**
     * delete from sys_user where data.id='784972358981328902'
     *
     * @param sql
     * @param params
     * @return
     * @Description: 执行sql
     */
    @Transactional
    public int executeSql(String sql, Map data) {
        return getBaseMapperCRUD().excuteBySql(sql, data);
    }

    /**
     * @param 设定
     * @return
     * @Description: 占位或非占位查询sql的查询唯一记录
     * @author 作者 jacking
     * @date 2017-6-17 下午4:05:05
     */
    public Object findBySqlUniqueObject(String sql, Class clz, Map params) {
        try {
            Map map = getBaseMapperCRUD().findBySqlUnique(sql, params);
            if (map != null && clz != null && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                return JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            } else {
                return map;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
    /**
     * @param 设定
     * @return
     * @Description: 固定泛型返回类型，占位或非占位查询sql的查询唯一记录
     * @author 作者 jacking
     * @date 2017-6-17 下午4:05:05
     */
    public <E> E findBySqlUniqueObjectNew(String sql, Class<E> clz, Map params) {
        try {
            Map map = getBaseMapperCRUD().findBySqlUnique(sql, params);
            if(map != null && clz != null && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))){
                return JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            }else if(map!=null&&(clz.getName().equals(Map.class.getName())||clz.getName().equals(HashMap.class.getName()))){
                return JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            }else{
                return null;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 查询单表实体列表
     *
     * @param clz
     * @return
     */
    public List findAll(Class clz) {
        List lst = new ArrayList<>();
        try {
            List<Map> l = getBaseMapperCRUD().selectAll(clz);
            for (Map map : l) {
                if (map != null) {
                    Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                    lst.add(o);
                }
            }
            return lst;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据不同的sql,参数，返回类型，灵活转换查询返回列表
     *
     * @param sql
     * @param clz
     * @param param
     * @return
     */
    public List findAll(String sql, Class clz, Map param) {
        List lst = new ArrayList<>();
        try {
            List<Map> l = getBaseMapperCRUD().findBySqlMore(sql, param);
            if (clz != null && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                for (Map map : l) {
                    if (map != null) {
                        Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                        lst.add(o);
                    }
                }
            } else {
                lst = l;
            }
            return lst;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 泛型获取实体，根据主键查询唯一
     *
     * @param clz
     * @param id
     * @return
     */
/*    public Object findById(String id) {
        Class clz = getEntityClass();
        Map map = getBaseMapperCRUD().selectById(clz, id);
        Object o = null;
        if (null != null) {
            try {
                o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return o;
    }*/

    /**
     * 根据主键查询唯一
     *
     * @param clz
     * @param id
     * @return
     */
    public Object findById(Class clz, String id) {
        Map map = getBaseMapperCRUD().selectById(clz, id);
        Object o = null;
        if (map!=null&&(!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
            try {
                o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            } catch (Exception e) {

                e.printStackTrace();
            }

        } else {
            o = map;
        }

        return o;

    }
    /**
     * 固定泛型返回类型，根据主键查询唯一
     * @param clz
     * @param id
     * @return
     */
    public <E> E findByIdNew(Class<E> clz, String id) {
        Map map = getBaseMapperCRUD().selectById(clz, id);
        try {
            if(map!=null&& (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))){
                return JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
        return null;

    }

    /**
     * @param 设定
     * @return
     * @Description: 占位或非占位sql查询记录,
     * @Description: TODO(描述)
     * @author 作者 jacking
     * @date 2017-6-17 下午4:05:37
     */
    public List findBySql(String sql, Class clz, Map params) {
        List lst = new ArrayList<>();
        try {
            List<Map> l = getBaseMapperCRUD().findBySqlMore(sql, params);
            if (null != clz && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                for (Map map : l) {
                    if (map != null) {
                        Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                        lst.add(o);
                    }
                }
            } else {
                lst = l;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return lst;
        }
        return lst;
    }

    /**
     * @param 设定
     * @return
     * @Description: 查询 ：执行存储过程
     * * callsql:
     * 例：@Select("call  procedureName()")
     * call procedureName(#{pojo.totalNum,jdbcType=INTEGER,mode=OUT},#{pojo.tableName,jdbcType=STRING,mode=IN},#{pojo.conditions,jdbcType=STRING,mode=IN})
     * @Description: TODO(描述)
     * @author 作者 jacking
     * @date 2017-6-17 下午3:57:57
     */
    public Object findByCallSql2Object(String callSql, Class clz, Map params) {
        if (clz != null && (clz.getName().equals(List.class.getName()) || clz.getName().equals(ArrayList.class.getName()))) {
            List lst = getBaseMapperCRUD().findByCallSql2List(callSql, params);
            return lst;
        } else if (null != clz && (clz.getName().equals(Map.class.getName()) || clz.getName().equals(HashMap.class.getName()))) {
            Map m = getBaseMapperCRUD().findByCallSql2Map(callSql, params);
            return m;
        } else {
            return null;
        }
    }

    /**
     * @param 设定
     * @return
     * @Description: 执行存储过程
     * * callsql:
     * 例：@Select("call  procedureName()")
     * call procedureName(#{pojo.totalNum,jdbcType=INTEGER,mode=OUT},#{pojo.tableName,jdbcType=STRING,mode=IN},#{pojo.conditions,jdbcType=STRING,mode=IN})
     * @Description: TODO(描述)
     * @author 作者 jacking
     * @date 2017-6-17 下午3:57:57
     */
    @Transactional
    public int excuteByCallSql(String callSql, Map params) {
        return getBaseMapperCRUD().excuteByCallSql(callSql, params);
    }

    /**
     * @param 设定
     * @return
     * @Description: 占位或非占位sql，自行类型转换的分页查询
     * @author 作者 jacking
     * @date 2017-6-17 下午4:06:35
     */
    public PageList findBySqlForPageList(String sql, Class clz, PageBean pageBean, Map params) {
        List lst = new ArrayList<>();
        try {
            if (null != pageBean) {
                Page p = PageHelper.startPage(pageBean.getPage(), pageBean.getPageSize()); //开始分页
                List<Map> l = getBaseMapperCRUD().findBySqlMore(sql, params);
                if (null != clz && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                    for (Map map : l) {
                        if (map != null) {
                            Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                            lst.add(o);
                        }
                    }
                } else {
                    lst = l;
                }
                pageBean = new PageBean(p.getTotal(), p.getPageNum(), p.getPageSize());
            } else {
                List<Map> l = getBaseMapperCRUD().findBySqlMore(sql, params);
                if (null != clz && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                    for (Map map : l) {
                        if (map != null) {
                            Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                            lst.add(o);
                        }
                    }
                } else {
                    lst = l;
                }
                pageBean = new PageBean();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return new PageList(lst, pageBean);
    }


    /**
     * SqlServer占位或非占位sql，自行类型转换的分页查询
     *
     * @param @param  rownumberDataSql
     *                sql="SELECT t.*,ROW_NUMBER() over(order by t.fieldName ASC ) as rownumber from tableName t";
     * @param @param  clz
     * @param @param  pageBean
     * @param @param  params
     * @param @return 设定文件
     * @return PageList    返回类型
     * @throws
     * @Title: queryForListBySqlServer
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public PageList queryForListBySqlServer(String rownumberDataSql, Class clz, PageBean pageBean, Map params) {
        List lst = new ArrayList<>();
        try {
            if (null != pageBean && rownumberDataSql != null && !"".equals(rownumberDataSql)) {
                String countsql = "SELECT count(*) countNum  from (" + rownumberDataSql + ") t";
                long totalCount = getBaseMapperCRUD().findCountBySql(countsql, params);
                pageBean = new PageBean(totalCount, pageBean.getPage(), pageBean.getPageSize());
                // 上一页的记录数位置
                int upPageCount = (pageBean.getPage() - 1) * pageBean.getPageSize();
                rownumberDataSql = "select top " + pageBean.getPageSize() + " data.* from ( " + rownumberDataSql + ") data WHERE data.rownumber > " + upPageCount;
                List<Map> l = getBaseMapperCRUD().findBySqlMore(rownumberDataSql, params);
                if (null != clz && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                    for (Map map : l) {
                        if (map != null) {
                            Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                            lst.add(o);
                        }
                    }
                } else {
                    lst = l;
                }
            } else {
                List<Map> l = getBaseMapperCRUD().findBySqlMore(rownumberDataSql, params);
                if (null != clz && (!clz.getName().equals(Map.class.getName()) && !clz.getName().equals(HashMap.class.getName()))) {
                    for (Map map : l) {
                        if (map != null) {
                            Object o = JsonUnderLineConvertUtils.toObjectByLineBean(map,clz);
                            lst.add(o);
                        }
                    }
                } else {
                    lst = l;
                }
                pageBean = new PageBean();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return new PageList(lst, pageBean);
    }

    /**
     * 截取原生sql后为count sql
     *
     * @param @param  sql
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getSubSql
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public String getSubSql(String sql) {
        int x1 = sql.indexOf("from") == -1 ? sql.indexOf("FROM") : sql.indexOf("from");
        int x2 = sql.indexOf("group by") == -1 ? sql.indexOf("GROUP BY") : sql.indexOf("group by");

        String h = "";
        if (x2 >= 0) {
            h = "select count(*) from (" + sql + ") temp";
        } else {
            h = "select count(*)  " + sql.substring(x1, sql.length());
        }
        int x3 = h.indexOf("order by");
        if (x3 >= 0) {
            h = h.substring(0, x3);
        }
        return h;
    }

 /*   *//**
     * 根据继承获取泛型的实体
     *
     * @return
     *//*
    public Class<T> getEntityClass() {
        Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return entityClass;
    }*/

    /**
     * 根据Class对象获取表名称
     *
     * @param clz
     * @return
     */
    public static String tableName(Class clz) {
        try {
            return MyBatisReflectUtil.tablename(clz.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据Class对象获取表主键id的字段名称
     *
     * @param clz
     * @return
     */
    public static String getTablePrimaryId(Class clz) {
        try {
           Field idname= MyBatisReflectUtil.idNew(clz.newInstance());
            final String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
            return dataIdname;
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param 设定
     * @return
     * @Description: 根据单一sql数据字段查询对象，固定泛型返回类型，占位或非占位查询sql的查询唯一记录
     * @author 作者 jacking
     * @date 2017-6-17 下午4:05:05
     */
    public <E> E findBySqlUniqueObjectColumn(String sql, Class<E> type, String column, Map params) {
        try {
            Map map = getBaseMapperCRUD().findBySqlUnique(sql, params);
            if (map!=null&&null != type && (!type.getName().equals(Map.class.getName()) && !type.getName().equals(HashMap.class.getName()))) {
                Object obj = map.get(column);
                return JsonUnderLineConvertUtils.toObjectByLineBean(obj, type);
            } else if(map!=null&&null != type && (type.getName().equals(Map.class.getName()) || type.getName().equals(HashMap.class.getName()))){
                Object obj = map.get(column);
                return JsonUnderLineConvertUtils.toObjectByLineBean(obj, type);
            } else{
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
    * @Description 根据单一sql数据字段查询列表，占位或非占位sql查询记录
    * @Author jiaojing
    * @Date 2021/4/30 16:59
    * @param sql
    * @param type
    * @param column
    * @param params
    * @return java.util.List
    */
    public List findBySql(String sql, Class type,String column, Map params) {
        List lst = new ArrayList<>();
        try {
            List<Map> l = getBaseMapperCRUD().findBySqlMore(sql, params);
            if (null != type && (!type.getName().equals(Map.class.getName()) && !type.getName().equals(HashMap.class.getName()))) {
                for (Map map : l) {
                    if (map != null) {
                        Object obj = map.get(column);
                        lst.add(JsonUnderLineConvertUtils.toObjectByLineBean(obj, type));
                    }
                }
            } else {
                lst = l;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return lst;
        }
        return lst;
    }
    /**
     * @Description 根据表名保存参数Map类型的数据，转换为表字段处理
     * @Author jiaojing
     * @Date 2021/4/19 11:04
     * @param objDataMap
     * @param tableName
     * @return int
     */
    @Transactional
    public int saveMap(Map<String, Object> objDataMap, String tableName) {
        return getBaseMapperCRUD().insertMap(objDataMap, tableName);
    }
    /**
     * @Description 根据表名，更新参数Map类型的数据，转换为表字段处理
     * @Author jiaojing
     * @Date 2021/4/19 10:45
     * @param objDataMap
     * @param tableName
     * @return int
     */
    @Transactional
    public int updateMap(Map<String, Object> objDataMap, String tableName) {
        return getBaseMapperCRUD().updateMap(objDataMap, tableName);
    }


}